<!doctype html>
<html>
<head>
<meta charset='UTF-8'><meta name='viewport' content='width=device-width initial-scale=1'>
<title>struct做模型初探，从入门到放弃.md</title></head>
<body><h1>struct做模型初探，从入门到放弃</h1>
<h2>尝鲜</h2>
<p>二版项目初期，为了让项目的swift化看起来更纯（zhuang）粹（bi），选择模型的类型时使用了struct，为什么使用struct？网上解释太多这里就不一一赘述。
好了，热火朝天干起来：</p>
<p>一个基本的模型大概是这样的：</p>
<pre><code>
struct User {
</code></pre>
<pre><code>
	/// 用户id
	var userId = 0
</code></pre>
<p>   		/// 用户名</p>
<pre><code>
	var userName = &quot;&quot;
</code></pre>
<pre><code>
	/// 关注我的人
	var fllower = [User]()
}
</code></pre>
<p>没什么问题吧？然而当你想要创建一个实例的时候，你会发现居然是这样的：
	</p>
<pre><code>
let user = User(userId: 1, userName: &quot;小明&quot;, fllower: [])
</code></pre>
<p>卧槽！excuseme？说好的kvc呢？说好的键值对编程呢？哦不对这个好像是NSObject的子类才有的方法吧？然而struct不能继承，怎么办，好方</p>
<h2>改进</h2>
<p>难道要在每次初始化的时候单独赋值？这也太恶心了，况且这不符合我这样高智（bi）商（ge）的码农的风格啊，痛定思痛，我找到了这样曲线救国的方法：
首先，我定义了一个协议如下：</p>
<pre><code>
protocol ModelProtocol {
</code></pre>
<pre><code>
init(dict: JSON)
</code></pre>
<pre><code>
}
</code></pre>
<p>其中‘JSON’类型来自<a href='https://github.com/SwiftyJSON/SwiftyJSON'>SwiftyJSON</a>（刚刚去看都有10000+个star了，看来转swift的人已经不少了）</p>
<p>然后我定义了这样的一些操作符重载：
	</p>
<pre><code>
infix operator &lt;== {
	associativity none
	precedence 130
}

func &lt;==(inout key:Bool, value:JSON) {
</code></pre>
<p>   		if let v = value.rawValue.boolValue {</p>
<pre><code>
   		 key = v
	}
}

...

func &lt;==&lt;U:ModelProtocol&gt;(inout key:U, value:JSON) {
</code></pre>
<p>  	  key = U(dict: value)</p>
<pre><code>
}
</code></pre>
<p></p>
<pre><code>
func &lt;==&lt;U:ModelProtocol&gt;(inout key:[U], value:JSON) {
</code></pre>
<p>   		if value.type == .Array {
      <br/></p>
<pre><code>
  		for dict in value.array! {
        	key.append(U(dict: dict))
    	}
	}
}

...
</code></pre>
<p>the next step,在User的init方法中这样实现:
	</p>
<pre><code>
init(dict: JSON) {
    userId      &lt;== dict[&quot;userId&quot;]
    userName    &lt;== dict[&quot;userName&quot;]
    follower    &lt;== dict[&quot;follower&quot;]
}
</code></pre>
<p>然后创建模型的操作也变成了这样：
	</p>
<pre><code>
let json = JSON(data: jsonData)
let user = User(dict: dict)
</code></pre>
<p>很爽很逼格有没有，这样的模型构造都可以直接写一个json转模型代码的脚本来跑了，自动化程度提高了n倍有没有？</p>
<h2>放弃</h2>
<p>为什么要放弃使用struct作为model？</p>
<p>这个数据层的架构是在项目准备重构的初期摸索出来的，这套架构被博主用得不亦乐乎，直到遇见<a href='https://realm.io/'>Realm</a>。</p>
<p>Realm和CoreData一样需要继承自他的一个统一父类，然而struct是不能继承的啊坑不坑？于是博主在尝试各种挣扎反抗无果后，灰溜溜的把模型换成了class，毕竟跟Realm的那些有点比起来，struct这种单纯装逼的特性有个吊用？（至于使用Realm遇到的各种坑，我会另外写一篇博客来详述）</p>
<p>题外话我是怎么转的：直接把所有的struct和ModelProtocol换成class,然后让ModelProtocol继承自Realm的Object、把不必要的代码删掉，轻松搞定！</p>
<p></p>
</body>
</html>